#include "gplib.h"
#include <stdio.h>
#include <math.h>

extern const int g_nByteOffset[4];
const int g_nRoundCnst = 49;
const int g_nRoundDiv = 100;
const int g_nThckRoundCnst = 99;
const int g_nSqrtPI_Remainder100 = 41;

extern inline int PointAssert(TGraphicContext *, int, int, char *);
int LineTo8(TGraphicContext *, int, int, TColor);
int LineTo16(TGraphicContext *, int, int, TColor);
int LineTo24(TGraphicContext *, int, int, TColor);
int XorLineTo8(TGraphicContext *, int, int, TColor);
int XorLineTo16(TGraphicContext *, int, int, TColor);
int XorLineTo24(TGraphicContext *, int, int, TColor);
int ThickLineTo8(TGraphicContext *, int, int, TColor);
int ThickLineTo16(TGraphicContext *, int, int, TColor);
int ThickLineTo24(TGraphicContext *, int, int, TColor);
int QuickThickLineTo8(TGraphicContext *, int, int, TColor);
int QuickThickLineTo16(TGraphicContext *, int, int, TColor);
int QuickThickLineTo24(TGraphicContext *, int, int, TColor);
int MaskLineTo8(TGraphicContext *, int, int, TColor);
int MaskLineTo16(TGraphicContext *, int, int, TColor);
int MaskLineTo24(TGraphicContext *, int, int, TColor);

#define ROUNDI(x) (((x) < 0) ? (int)((x) - 0.5) : (int)((x) + 0.5))

/**
 * Рисование линии единичной толщины от текущих координат
 * @param указатель на графический контекст
 * @param конечная координата по X
 * @param конечная координата по Y
 * @param цвет
 * @return код ошибки
 */
int LineTo(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nRet = GP_ERR;

	if (PointAssert(ctx, x2, y2, "LineTo") != GP_OK) {
		return nRet;
	}

	switch (ctx->nBitsPerPixel) {
	case 8:
		nRet = LineTo8(ctx, x2, y2, Color);
		break;
	case 16:
		nRet = LineTo16(ctx, x2, y2, Color);
		break;
	case 24:
		nRet = LineTo24(ctx, x2, y2, Color);
		break;
	}

	return nRet;
}

int LineTo8(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	char bReorder = ctx->bReorder;

	SET_PIXEL_8(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr++;
					SET_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr += nBytesPerLine;
					SET_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr++;
					SET_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr -= nBytesPerLine;
					SET_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr++;
				SET_PIXEL_8(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr--;
					SET_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr += nBytesPerLine;
					SET_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr--;
					SET_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr -= nBytesPerLine;
					SET_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr--;
				SET_PIXEL_8(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_PIXEL_8(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_PIXEL_8(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

int LineTo16(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;

	SET_PIXEL_16(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr += nBytesPerPixel;
				SET_PIXEL_16(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr -= nBytesPerPixel;
				SET_PIXEL_16(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_PIXEL_16(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_PIXEL_16(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

int LineTo24(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;

	SET_PIXEL_24(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr += nBytesPerPixel;
				SET_PIXEL_24(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr -= nBytesPerPixel;
				SET_PIXEL_24(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_PIXEL_24(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_PIXEL_24(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

/**
 * Рисование линии единичной толщины от текущих координат с наложением по модулю 2 с содержимым экрана
 * @param указатель на графический контекст
 * @param конечная координата по X
 * @param конечная координата по Y
 * @param цвет
 * @return код ошибки
 */
int XorLineTo(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nRet = GP_ERR;

	if (PointAssert(ctx, x2, y2, "XorLineTo") != GP_OK) {
		return GP_ERR;
	}

	switch (ctx->nBitsPerPixel) {
	case 8:
		nRet = XorLineTo8(ctx, x2, y2, Color);
		break;
	case 16:
		nRet = XorLineTo16(ctx, x2, y2, Color);
		break;
	case 24:
		nRet = XorLineTo24(ctx, x2, y2, Color);
		break;
	}

	return nRet;
}

int XorLineTo8(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	char bReorder = ctx->bReorder;

	SET_XOR_PIXEL_8(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr++;
					SET_XOR_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr += nBytesPerLine;
					SET_XOR_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr++;
					SET_XOR_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr -= nBytesPerLine;
					SET_XOR_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr++;
				SET_XOR_PIXEL_8(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr--;
					SET_XOR_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr += nBytesPerLine;
					SET_XOR_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr--;
					SET_XOR_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr -= nBytesPerLine;
					SET_XOR_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr--;
				SET_XOR_PIXEL_8(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_XOR_PIXEL_8(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_XOR_PIXEL_8(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

int XorLineTo16(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;

	SET_XOR_PIXEL_16(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_XOR_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_XOR_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_XOR_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_XOR_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr += nBytesPerPixel;
				SET_XOR_PIXEL_16(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_XOR_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_XOR_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_XOR_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_XOR_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr -= nBytesPerPixel;
				SET_XOR_PIXEL_16(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_XOR_PIXEL_16(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_XOR_PIXEL_16(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

int XorLineTo24(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;

	SET_XOR_PIXEL_24(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_XOR_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_XOR_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_XOR_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_XOR_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr += nBytesPerPixel;
				SET_XOR_PIXEL_24(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_XOR_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_XOR_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_XOR_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_XOR_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr -= nBytesPerPixel;
				SET_XOR_PIXEL_24(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_XOR_PIXEL_24(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_XOR_PIXEL_24(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

#define DrawAlongYXMinus(SET_PIXEL) 					\
	if (nCurrentPos & nLineMask) { 						\
		pTmpScrPtr = pScrPtr - nThOffs;   				\
        nInD = nCpD;                					\
        												\
        for (nCnt = 0; nCnt < pointsInLine; nCnt++) {	\
        	SET_PIXEL(pTmpScrPtr, &Color) 				\
        												\
            if (nInD < 0) { 							\
				nInD += nEStep; 						\
            } else { 									\
            	nInD += nCorrection; 					\
                pTmpScrPtr -= nBytesPerPixel; 			\
                										\
                if (bDrawAddonPixel) { 					\
                	SET_PIXEL(pTmpScrPtr, &Color)		\
                } 										\
            }                         					\
            pTmpScrPtr += nBytesPerLine;      			\
        }                             					\
	}                                					\
	nCurrentPos <<= 1;                  				\
														\
	if (nCurrentPos == nLineMaskPos) {					\
		nCurrentPos = 1;								\
	}

#define DrawAlongYXPlus(SET_PIXEL)    					\
	if (nCurrentPos & nLineMask) { 						\
		pTmpScrPtr = pScrPtr - nThOffs;   				\
		nInD = nCpD;                					\
														\
		for (nCnt = 0; nCnt < pointsInLine; nCnt++) {	\
			SET_PIXEL(pTmpScrPtr, &Color) 				\
														\
			if (nInD < 0) {								\
				nInD += nEStep;  						\
			} else {                  	 				\
				nInD += nCorrection;    				\
				pTmpScrPtr += nBytesPerPixel;           \
														\
				if (bDrawAddonPixel) {     				\
					SET_PIXEL(pTmpScrPtr, &Color) 		\
				}										\
			}                         					\
			pTmpScrPtr += nBytesPerLine;      			\
		}                             					\
	}                                					\
	nCurrentPos <<= 1;                  				\
														\
	if (nCurrentPos == nLineMaskPos) {					\
		nCurrentPos = 1;								\
	}													\

#define DrawAlongXYMinus(SET_PIXEL)						\
	if (nCurrentPos & nLineMask) { 						\
		pTmpScrPtr = pScrPtr - nThOffs;   				\
		nInD = nCpD;                					\
														\
		for (nCnt = 0; nCnt < pointsInLine; nCnt++) {	\
			SET_PIXEL(pTmpScrPtr, &Color) 				\
                                   	   	   	   	   		\
			if (nInD < 0) {								\
				nInD += nEStep;  						\
			} else {                  					\
				nInD += nCorrection;    				\
				pTmpScrPtr -= nBytesPerLine;  			\
                                      	  	  	  		\
				if (bDrawAddonPixel) {     				\
					SET_PIXEL(pTmpScrPtr, &Color) 		\
				}										\
			}                         					\
			pTmpScrPtr += nBytesPerPixel;               \
		}                             					\
	}                                					\
	nCurrentPos <<= 1;                  				\
														\
	if (nCurrentPos == nLineMaskPos) {					\
		nCurrentPos = 1;								\
	}

#define DrawAlongXYPlus(SET_PIXEL)						\
	if (nCurrentPos & nLineMask) { 						\
		pTmpScrPtr = pScrPtr - nThOffs;   				\
		nInD = nCpD;                					\
                                						\
		for (nCnt = 0; nCnt < pointsInLine; nCnt++) {	\
			SET_PIXEL(pTmpScrPtr, &Color) 				\
														\
			if (nInD < 0) {								\
				nInD += nEStep;  						\
			} else {                  					\
				nInD += nCorrection;    				\
				pTmpScrPtr += nBytesPerLine;  			\
                                      	  	  	  		\
				if (bDrawAddonPixel) {    				\
					SET_PIXEL(pTmpScrPtr, &Color) 		\
				}										\
			}                         					\
			pTmpScrPtr += nBytesPerPixel;               \
		}                             					\
	}                                					\
	nCurrentPos <<= 1;                  				\
														\
	if (nCurrentPos == nLineMaskPos) {					\
		nCurrentPos = 1;								\
	}

#define DrawAlongX(SET_PIXEL)    						\
	if (nCurrentPos&nLineMask) {  						\
		pTmpScrPtr = pScrPtr - ThOffsX;   				\
                                						\
		for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {	\
			SET_PIXEL(pTmpScrPtr, &Color) 				\
			pTmpScrPtr += nBytesPerPixel;               \
		}                             					\
	}                                					\
	nCurrentPos <<= 1;                  				\
														\
	if (nCurrentPos == nLineMaskPos) {					\
		nCurrentPos = 1;								\
	}

#define DrawAlongY(SET_PIXEL)							\
	if (nCurrentPos&nLineMask) {  						\
		pTmpScrPtr = pScrPtr - ThOffsY;   				\
														\
		for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {	\
			SET_PIXEL(pTmpScrPtr, &Color) 				\
			pTmpScrPtr += nBytesPerLine;  				\
		}                             					\
	}                                					\
	nCurrentPos <<= 1;                  				\
														\
	if (nCurrentPos == nLineMaskPos) {					\
		nCurrentPos = 1;								\
	}

/**
 * Рисование линии от текущих координат с текущей толщиной и указанной маской
 * @param указатель на графический контекст
 * @param конечная координата по X
 * @param конечная координата по Y
 * @param цвет
 * @return код ошибки
 */
int ThickLineTo(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nRet = GP_ERR;

	if (PointAssert(ctx, x2, y2, "ThickLineTo") != GP_OK) {
		return nRet;
	}

	switch (ctx->nBitsPerPixel) {
	case 8:
		nRet = ThickLineTo8(ctx, x2, y2, Color);
		break;
	case 16:
		nRet = ThickLineTo16(ctx, x2, y2, Color);
		break;
	case 24:
		nRet = ThickLineTo24(ctx, x2, y2, Color);
		break;
	}

	return nRet;
}

int ThickLineTo8(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	char *pTmpScrPtr;
	int nCnt;
	int nCpD, nInD;
	int nThOffs, nG;
	int pointsInLine = ctx->nCurrentThickness;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;
	unsigned int nCurrentPos = ctx->nCurrentPos;
	unsigned int nLineMask = ctx->nLineMask;
	unsigned int nLineMaskPos = ctx->nLineMaskPos;
	char bDrawAddonPixel = ctx->bDrawAddonPixel;
	char nCurrentThickness = ctx->nCurrentThickness;
	int ThOffsX = ctx->nThOffsX;
	int ThOffsY = ctx->nThOffsY;

	if (ctx->nCurrentPos == ctx->nLineMaskPos) {
		ctx->nCurrentPos = 1;
	}

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;
				nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine - (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXMinus(SET_PIXEL_8)

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr++;
					DrawAlongYXMinus(SET_PIXEL_8)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;
				nThOffs = -((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYMinus(SET_PIXEL_8)

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr += nBytesPerLine;
					DrawAlongXYMinus(SET_PIXEL_8)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));
			nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXPlus(SET_PIXEL_8)

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr++;
					DrawAlongYXPlus(SET_PIXEL_8)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYPlus(SET_PIXEL_8)

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr -= nBytesPerLine;
					DrawAlongXYPlus(SET_PIXEL_8)
				}
			}
		} else {
			DrawAlongY(SET_PIXEL_8)

			for (x1++; x1 <= x2; x1++) {
				pScrPtr++;
				DrawAlongY(SET_PIXEL_8)
			}
		}
	} else if (x2 < x1) {
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));
			nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXPlus(SET_PIXEL_8)

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr--;
					DrawAlongYXPlus(SET_PIXEL_8)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYPlus(SET_PIXEL_8)

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr += nBytesPerLine;
					DrawAlongXYPlus(SET_PIXEL_8)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;
				nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine - (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXMinus(SET_PIXEL_8)

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr--;
					DrawAlongYXMinus(SET_PIXEL_8)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;
				nThOffs = -((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYMinus(SET_PIXEL_8)

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr -= nBytesPerLine;
					DrawAlongXYMinus(SET_PIXEL_8)
				}
			}
		} else {
			DrawAlongY(SET_PIXEL_8)

			for (x1--; x1 >= x2; x1--) {
				pScrPtr--;
				DrawAlongY(SET_PIXEL_8)
			}
		}
	} else {
		if (y2 > y1) {
			DrawAlongX(SET_PIXEL_8)

			for (y1++; y1 <= y2; y1++) {
				pScrPtr+=nBytesPerLine;
				DrawAlongX(SET_PIXEL_8)
			}
		} else {
			DrawAlongX(SET_PIXEL_8)

			for (y1--; y1 >= y2; y1--) {
				pScrPtr -= nBytesPerLine;
				DrawAlongX(SET_PIXEL_8)
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

int ThickLineTo16(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	char *pTmpScrPtr;
	int nCnt;
	int nCpD, nInD;
	int nThOffs, nG;
	int pointsInLine = ctx->nCurrentThickness;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;
	unsigned int nCurrentPos = ctx->nCurrentPos;
	unsigned int nLineMask = ctx->nLineMask;
	unsigned int nLineMaskPos = ctx->nLineMaskPos;
	char bDrawAddonPixel = ctx->bDrawAddonPixel;
	char nCurrentThickness = ctx->nCurrentThickness;
	int ThOffsX = ctx->nThOffsX;
	int ThOffsY = ctx->nThOffsY;

	if (ctx->nCurrentPos == ctx->nLineMaskPos) {
		ctx->nCurrentPos = 1;
	}

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;
				nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine - (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXMinus(SET_PIXEL_16)

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					DrawAlongYXMinus(SET_PIXEL_16)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;
				nThOffs = -((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYMinus(SET_PIXEL_16)

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					DrawAlongXYMinus(SET_PIXEL_16)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));
			nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXPlus(SET_PIXEL_16)

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					DrawAlongYXPlus(SET_PIXEL_16)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYPlus(SET_PIXEL_16)

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					DrawAlongXYPlus(SET_PIXEL_16)
				}
			}
		} else {
			DrawAlongY(SET_PIXEL_16)

			for (x1++; x1 <= x2; x1++) {
				pScrPtr += nBytesPerPixel;
				DrawAlongY(SET_PIXEL_16)
			}
		}
	} else if (x2 < x1) {
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));
			nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXPlus(SET_PIXEL_16)

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					DrawAlongYXPlus(SET_PIXEL_16)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYPlus(SET_PIXEL_16)

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					DrawAlongXYPlus(SET_PIXEL_16)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;
				nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine - (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXMinus(SET_PIXEL_16)

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					DrawAlongYXMinus(SET_PIXEL_16)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;
				nThOffs = -((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYMinus(SET_PIXEL_16)

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					DrawAlongXYMinus(SET_PIXEL_16)
				}
			}
		} else {
			DrawAlongY(SET_PIXEL_16)

			for (x1--; x1 >= x2; x1--) {
				pScrPtr -= nBytesPerPixel;
				DrawAlongY(SET_PIXEL_16)
			}
		}
	} else {
		if (y2 > y1) {
			DrawAlongX(SET_PIXEL_16)

			for (y1++; y1 <= y2; y1++) {
				pScrPtr+=nBytesPerLine;
				DrawAlongX(SET_PIXEL_16)
			}
		} else {
			DrawAlongX(SET_PIXEL_16)

			for (y1--; y1 >= y2; y1--) {
				pScrPtr -= nBytesPerLine;
				DrawAlongX(SET_PIXEL_16)
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

int ThickLineTo24(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	char *pTmpScrPtr;
	int nCnt;
	int nCpD, nInD;
	int nThOffs, nG;
	int pointsInLine = ctx->nCurrentThickness;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;
	unsigned int nCurrentPos = ctx->nCurrentPos;
	unsigned int nLineMask = ctx->nLineMask;
	unsigned int nLineMaskPos = ctx->nLineMaskPos;
	char bDrawAddonPixel = ctx->bDrawAddonPixel;
	char nCurrentThickness = ctx->nCurrentThickness;
	int ThOffsX = ctx->nThOffsX;
	int ThOffsY = ctx->nThOffsY;

	if (ctx->nCurrentPos == ctx->nLineMaskPos) {
		ctx->nCurrentPos = 1;
	}

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;
				nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine - (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXMinus(SET_PIXEL_24)

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					DrawAlongYXMinus(SET_PIXEL_24)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;
				nThOffs = -((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYMinus(SET_PIXEL_24)

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					DrawAlongXYMinus(SET_PIXEL_24)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));
			nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXPlus(SET_PIXEL_24)

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					DrawAlongYXPlus(SET_PIXEL_24)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYPlus(SET_PIXEL_24)

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					DrawAlongXYPlus(SET_PIXEL_24)
				}
			}
		} else {
			DrawAlongY(SET_PIXEL_24)

			for (x1++; x1 <= x2; x1++) {
				pScrPtr += nBytesPerPixel;
				DrawAlongY(SET_PIXEL_24)
			}
		}
	} else if (x2 < x1) {
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));
			nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXPlus(SET_PIXEL_24)

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					DrawAlongYXPlus(SET_PIXEL_24)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYPlus(SET_PIXEL_24)

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					DrawAlongXYPlus(SET_PIXEL_24)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;
			nG = ROUNDI(sqrt(nDx * nDx + nDy * nDy));

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nCpD = nD;
				nEStep = nDy << 1;
				nCorrection = nD << 1;
				nThOffs = ((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine - (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDy / nDx) + g_nThckRoundCnst) / 100;
				} else if (nDx == nDy && ctx->bSimpleRecalcThick) {
					--pointsInLine;
				}
				DrawAlongYXMinus(SET_PIXEL_24)

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					DrawAlongYXMinus(SET_PIXEL_24)
				}
			} else {
				nD = nDx - nDy;
				nCpD = nD;
				nEStep = nDx << 1;
				nCorrection = nD << 1;
				nThOffs = -((ctx->nThOffsX100 * nDx / nG + g_nRoundCnst) / g_nRoundDiv) * nBytesPerLine + (ctx->nThOffsX100 * nDy / nG + g_nRoundCnst) / g_nRoundDiv;

				if (ctx->bRecalcThick) {
					pointsInLine = (ctx->nCurrentThickness * 10000 / (100 + g_nSqrtPI_Remainder100 * nDx / nDy) + g_nThckRoundCnst) / 100;
				}
				DrawAlongXYMinus(SET_PIXEL_24)

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					DrawAlongXYMinus(SET_PIXEL_24)
				}
			}
		} else {
			DrawAlongY(SET_PIXEL_24)

			for (x1--; x1 >= x2; x1--) {
				pScrPtr -= nBytesPerPixel;
				DrawAlongY(SET_PIXEL_24)
			}
		}
	} else {
		if (y2 > y1) {
			DrawAlongX(SET_PIXEL_24)

			for (y1++; y1 <= y2; y1++) {
				pScrPtr+=nBytesPerLine;
				DrawAlongX(SET_PIXEL_24)
			}
		} else {
			DrawAlongX(SET_PIXEL_24)

			for (y1--; y1 >= y2; y1--) {
				pScrPtr -= nBytesPerLine;
				DrawAlongX(SET_PIXEL_24)
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

	return GP_OK;
}

/**
 * Рисование линии от текущих координат с текущей толщиной и указанной маской (более быстрая отрисовка за счет концов линий)
 * @param указатель на графический контекст
 * @param конечная координата по X
 * @param конечная координата по Y
 * @param цвет
 * @return код ошибки
 */
int QuickThickLineTo(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nRet = GP_ERR;

	if (PointAssert(ctx, x2, y2, "QuickThickLineTo") != GP_OK) {
		return nRet;
	}

	switch (ctx->nBitsPerPixel) {
	case 8:
		nRet = QuickThickLineTo8(ctx, x2, y2, Color);
		break;
	case 16:
		nRet = QuickThickLineTo16(ctx, x2, y2, Color);
		break;
	case 24:
		nRet = QuickThickLineTo24(ctx, x2, y2, Color);
		break;
	}

	return nRet;
}

int QuickThickLineTo8(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	char *pTmpScrPtr;
	int nCnt;
  	int nBytesPerLine = ctx->nBytesPerLine;
  	char bReorder = ctx->bReorder;
  	unsigned int nCurrentPos = ctx->nCurrentPos;
  	unsigned int nLineMask = ctx->nLineMask;
  	unsigned int nLineMaskPos = ctx->nLineMaskPos;
  	char nCurrentThickness = ctx->nCurrentThickness;
  	int ThOffsX = ctx->nThOffsX;
  	int ThOffsY = ctx->nThOffsY;

	if (nCurrentPos == nLineMaskPos) {
	   nCurrentPos = 1;
	}

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr++;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_8(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
				  	nCurrentPos <<= 1;

				  	if (nCurrentPos == nLineMaskPos) {
				  		nCurrentPos = 1;
				  	}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr++;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr += nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_8(pTmpScrPtr, &Color)
							pTmpScrPtr++;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr++;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_8(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr++;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
				  	nCurrentPos = 1;
				}

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
					   	pScrPtr++;
				  	}
					pScrPtr -= nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_8(pTmpScrPtr, &Color)
							pTmpScrPtr++;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else {
			for (; x1 <= x2; x1++) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr++;
			}
		}
	} else if (x2 < x1) {
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr--;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_8(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr++;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr += nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_8(pTmpScrPtr, &Color)
							pTmpScrPtr++;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr--;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_8(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++){
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr++;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr -= nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_8(pTmpScrPtr, &Color)
							pTmpScrPtr++;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else {
			for (; x1 >= x2; x1--) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr--;
			}
		}
	} else {
		if (y2 > y1) {
			for (; y1 <= y2; y1++) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr++;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (; y1 >= y2; y1--) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_8(pTmpScrPtr, &Color)
						pTmpScrPtr++;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

   return GP_OK;
}

int QuickThickLineTo16(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	char *pTmpScrPtr;
	int nCnt;
  	int nBytesPerLine = ctx->nBytesPerLine;
  	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
  	char bReorder = ctx->bReorder;
  	unsigned int nCurrentPos = ctx->nCurrentPos;
  	unsigned int nLineMask = ctx->nLineMask;
  	unsigned int nLineMaskPos = ctx->nLineMaskPos;
  	char nCurrentThickness = ctx->nCurrentThickness;
  	int ThOffsX = ctx->nThOffsX;
  	int ThOffsY = ctx->nThOffsY;

	if (nCurrentPos == nLineMaskPos) {
	   nCurrentPos = 1;
	}

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_16(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
				  	nCurrentPos <<= 1;

				  	if (nCurrentPos == nLineMaskPos) {
				  		nCurrentPos = 1;
				  	}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_16(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerPixel;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_16(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
				  	nCurrentPos = 1;
				}

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
					   	pScrPtr += nBytesPerPixel;
				  	}
					pScrPtr -= nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_16(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerPixel;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else {
			for (; x1 <= x2; x1++) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr += nBytesPerPixel;
			}
		}
	} else if (x2 < x1) {
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_16(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_16(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerPixel;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_16(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++){
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_16(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerPixel;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else {
			for (; x1 >= x2; x1--) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr -= nBytesPerPixel;
			}
		}
	} else {
		if (y2 > y1) {
			for (; y1 <= y2; y1++) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (; y1 >= y2; y1--) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_16(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

   return GP_OK;
}

int QuickThickLineTo24(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	char *pTmpScrPtr;
	int nCnt;
  	int nBytesPerLine = ctx->nBytesPerLine;
  	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
  	char bReorder = ctx->bReorder;
  	unsigned int nCurrentPos = ctx->nCurrentPos;
  	unsigned int nLineMask = ctx->nLineMask;
  	unsigned int nLineMaskPos = ctx->nLineMaskPos;
  	char nCurrentThickness = ctx->nCurrentThickness;
  	int ThOffsX = ctx->nThOffsX;
  	int ThOffsY = ctx->nThOffsY;

	if (nCurrentPos == nLineMaskPos) {
	   nCurrentPos = 1;
	}

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_24(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
				  	nCurrentPos <<= 1;

				  	if (nCurrentPos == nLineMaskPos) {
				  		nCurrentPos = 1;
				  	}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_24(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerPixel;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_24(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
				  	nCurrentPos = 1;
				}

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
					   	pScrPtr += nBytesPerPixel;
				  	}
					pScrPtr -= nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_24(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerPixel;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else {
			for (; x1 <= x2; x1++) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr += nBytesPerPixel;
			}
		}
	} else if (x2 < x1) {
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_24(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_24(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerPixel;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsY;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_24(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerLine;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++){
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;

					if (nCurrentPos & nLineMask) {
						pTmpScrPtr = pScrPtr - ThOffsX;

						for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
							SET_PIXEL_24(pTmpScrPtr, &Color)
							pTmpScrPtr += nBytesPerPixel;
						}
					}
					nCurrentPos <<= 1;

					if (nCurrentPos == nLineMaskPos) {
						nCurrentPos = 1;
					}
				}
			}
		} else {
			for (; x1 >= x2; x1--) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsY;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerLine;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr -= nBytesPerPixel;
			}
		}
	} else {
		if (y2 > y1) {
			for (; y1 <= y2; y1++) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (; y1 >= y2; y1--) {
				if (nCurrentPos & nLineMask) {
					pTmpScrPtr = pScrPtr - ThOffsX;

					for (nCnt = 0; nCnt < nCurrentThickness; nCnt++) {
						SET_PIXEL_24(pTmpScrPtr, &Color)
						pTmpScrPtr += nBytesPerPixel;
					}
				}
				nCurrentPos <<= 1;

				if (nCurrentPos == nLineMaskPos) {
					nCurrentPos = 1;
				}
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;

   return GP_OK;
}

/**
 * Рисование линии единичной толщины от текущих координат с указанной маской
 * @param указатель на графический контекст
 * @param конечная координата по X
 * @param конечная координата по Y
 * @param цвет
 * @return код ошибки
 */
int MaskLineTo(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nRet = GP_ERR;

	if (PointAssert(ctx, x2, y2, "MaskLineTo") != GP_OK) {
		return nRet;
	}

	switch (ctx->nBitsPerPixel) {
	case 8:
		nRet = MaskLineTo8(ctx, x2, y2, Color);
		break;
	case 16:
		nRet = MaskLineTo16(ctx, x2, y2, Color);
		break;
	case 24:
		nRet = MaskLineTo24(ctx, x2, y2, Color);
		break;
	}

	return nRet;
}

int MaskLineTo8(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	char bReorder = ctx->bReorder;
	unsigned int nLineMask = ctx->nLineMask;
	unsigned int nCurrentPos = ctx->nCurrentPos;
	unsigned int nLineMaskPos = ctx->nLineMaskPos;

	SET_MASKED_PIXEL_8(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr++;
					SET_MASKED_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr += nBytesPerLine;
					SET_MASKED_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr++;
					SET_MASKED_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr++;
					}
					pScrPtr -= nBytesPerLine;
					SET_MASKED_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr++;
				SET_MASKED_PIXEL_8(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr--;
					SET_MASKED_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr += nBytesPerLine;
					SET_MASKED_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr--;
					SET_MASKED_PIXEL_8(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr--;
					}
					pScrPtr -= nBytesPerLine;
					SET_MASKED_PIXEL_8(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr--;
				SET_MASKED_PIXEL_8(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_MASKED_PIXEL_8(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_MASKED_PIXEL_8(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;
	ctx->nCurrentPos = nCurrentPos;

	return GP_OK;
}

int MaskLineTo16(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;
	unsigned int nLineMask = ctx->nLineMask;
	unsigned int nCurrentPos = ctx->nCurrentPos;
	unsigned int nLineMaskPos = ctx->nLineMaskPos;

	SET_MASKED_PIXEL_16(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_MASKED_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_MASKED_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_MASKED_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_MASKED_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr += nBytesPerPixel;
				SET_MASKED_PIXEL_16(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_MASKED_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_MASKED_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_MASKED_PIXEL_16(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_MASKED_PIXEL_16(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr -= nBytesPerPixel;
				SET_MASKED_PIXEL_16(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_MASKED_PIXEL_16(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_MASKED_PIXEL_16(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;
	ctx->nCurrentPos = nCurrentPos;

	return GP_OK;
}

int MaskLineTo24(TGraphicContext *ctx, int x2, int y2, TColor Color) {
	int nD;
	int x1 = ctx->nLastPositionX;
	int y1 = ctx->nLastPositionY;
	unsigned int nDx, nDy;
	int nEStep, nCorrection;
	char *pScrPtr = ctx->pLastScreenPos;
	int nBytesPerLine = ctx->nBytesPerLine;
	int nBytesPerPixel = ctx->nBitsPerPixel / 8;
	char bReorder = ctx->bReorder;
	unsigned int nLineMask = ctx->nLineMask;
	unsigned int nCurrentPos = ctx->nCurrentPos;
	unsigned int nLineMaskPos = ctx->nLineMaskPos;

	SET_MASKED_PIXEL_24(pScrPtr, &Color)

	if (x2 > x1) {
		nDx = x2 - x1;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_MASKED_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_MASKED_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1++; x1 <= x2; x1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr += nBytesPerPixel;
					SET_MASKED_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_MASKED_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else {
			for (x1++; x1 <= x2; x1++) {
				pScrPtr += nBytesPerPixel;
				SET_MASKED_PIXEL_24(pScrPtr, &Color)
			}
		}
	} else if (x2 < x1)	{
		nDx = x1 - x2;

		if (y2 > y1) {
			nDy = y2 - y1;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr += nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_MASKED_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1++; y1 <= y2; y1++) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr += nBytesPerLine;
					SET_MASKED_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else if (y2 < y1) {
			nDy = y1 - y2;

			if (nDx >= nDy) {
				nD = nDy - nDx;
				nEStep = nDy << 1;
				nCorrection = nD << 1;

				for (x1--; x1 >= x2; x1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerLine;
					}
					pScrPtr -= nBytesPerPixel;
					SET_MASKED_PIXEL_24(pScrPtr, &Color)
				}
			} else {
				nD = nDx - nDy;
				nEStep = nDx << 1;
				nCorrection = nD << 1;

				for (y1--; y1 >= y2; y1--) {
					if (nD < 0) {
						nD += nEStep;
					} else {
						nD += nCorrection;
						pScrPtr -= nBytesPerPixel;
					}
					pScrPtr -= nBytesPerLine;
					SET_MASKED_PIXEL_24(pScrPtr, &Color)
				}
			}
		} else {
			for (x1--; x1 >= x2; x1--) {
				pScrPtr -= nBytesPerPixel;
				SET_MASKED_PIXEL_24(pScrPtr, &Color)
			}
		}
	} else {
		if (y2 > y1) {
			for (y1++; y1 <= y2; y1++) {
				SET_MASKED_PIXEL_24(pScrPtr, &Color)
				pScrPtr += nBytesPerLine;
			}
		} else {
			for (y1--; y1 >= y2; y1--) {
				SET_MASKED_PIXEL_24(pScrPtr, &Color)
				pScrPtr -= nBytesPerLine;
			}
		}
	}
	ctx->nLastPositionX = x2;
	ctx->nLastPositionY = y2;
	ctx->pLastScreenPos = pScrPtr;
	ctx->nCurrentPos = nCurrentPos;

	return GP_OK;
}
